package jmine.tec.hydra.domain.actions;

import java.util.Collections;
import java.util.List;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;

import jmine.tec.executionlog.dao.ExecutionLogItemDAO;
import jmine.tec.executionlog.domain.ExecutionLog;
import jmine.tec.executionlog.domain.ExecutionLogItem;
import jmine.tec.executionlog.domain.enumx.ExecutionItemStatus;
import jmine.tec.hydra.api.FailedServicePageAction;
import jmine.tec.hydra.api.HydraAction;
import jmine.tec.persist.annotation.DiscriminatorComment;
import jmine.tec.persist.annotation.Index;

import org.hibernate.annotations.ForeignKey;

import bancosys.tec.component.Documentation;

/**
 * Action que representa uma página de serviços cuja execução falhou. Esta fase resulta invariavelmente em erro e serve apenas para
 * registrar a falha e permitir ao usuário a fácil visualização e resolução do problema
 * 
 * @author lundberg
 */
@Entity
@DiscriminatorValue("3")
@DiscriminatorComment("REGISTRO DE FALHA DE SERVICO")
public class DefaultFailedServicePageAction extends AbstractHydraAction implements FailedServicePageAction {

    private ExecutionLog executionLog;

    private ExecutionLogItem failedFrom;

    private ExecutionLogItem failedTo;

    /**
     * {@inheritDoc}
     */
    public FailedServicePageAction prepare(ExecutionLog execLog, ExecutionLogItem from, ExecutionLogItem to) {
        this.executionLog = execLog;
        this.failedFrom = from;
        this.failedTo = to;
        return this;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected List<HydraAction> doExecute() throws Exception {
        this.markAsPending();
        for (ExecutionLogItem item : this.getFailedItems()) {
            if (ExecutionItemStatus.NOT_OK.equals(item.getStatus())) {
                if (item.getMessage() != null) {
                    this.logAsSystem(item.getServiceLocation() != null ? item.getServiceLocation().concat(": ").concat(item.getMessage())
                            : item.getMessage());
                }
            }
        }
        return Collections.emptyList();
    }

    /**
     * {@inheritDoc}
     */
    @Transient
    public List<ExecutionLogItem> getFailedItems() {
        ExecutionLogItemDAO dao = this.getController().getDAOFactory().getDAOByClass(ExecutionLogItemDAO.class);
        return dao.findItemsBetween(this.getFailedFrom(), this.getFailedTo());
    }

    // Documentation do campo presente em DecodeMessageAction
    /**
     * {@inheritDoc}
     */
    @Index(suffix = "JT_0")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "COD_EXECUTION_LOG")
    public ExecutionLog getExecutionLog() {
        return this.executionLog;
    }

    /**
     * {@inheritDoc}
     */
    @Index(suffix = "JT_1")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "COD_EXECUTION_LOG_ITEM_FROM")
    @Documentation("CODIGO DO PRIMEIRO ITEM DE LOG QUE CORRESPONDE A FALHA")
    public ExecutionLogItem getFailedFrom() {
        return this.failedFrom;
    }

    /**
     * {@inheritDoc}
     */
    @Index(suffix = "JT_2")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "COD_EXECUTION_LOG_ITEM_TO")
    @Documentation("CODIGO DO ULTIMO ITEM DE LOG QUE CORRESPONDE A FALHA")
    @ForeignKey(name = "FK_EXELOI_HYACTI_2")
    public ExecutionLogItem getFailedTo() {
        return this.failedTo;
    }

    /**
     * @param executionLog the executionLog to set
     */
    public void setExecutionLog(ExecutionLog executionLog) {
        this.executionLog = executionLog;
    }

    /**
     * @param failedFrom the failedFrom to set
     */
    public void setFailedFrom(ExecutionLogItem failedFrom) {
        this.failedFrom = failedFrom;
    }

    /**
     * @param failedTo the failedTo to set
     */
    public void setFailedTo(ExecutionLogItem failedTo) {
        this.failedTo = failedTo;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String createDescription() {
        return "Serviços que resultaram em erro.";
    }
}
